package com.exoweb.common.business {
    import mx.core.Application;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.events.InvokeEvent;
    import mx.rpc.remoting.mxml.RemoteObject;

    import com.exoweb.common.Config;
    import com.exoweb.common.Constants;
    import com.exoweb.common.PopUpMessageManager;
    import com.exoweb.common.view.ErrorMessage;

    // subclass should be singleton
    public class GameService {
        public var remoteObject:RemoteObject;
        public var model:*;
        public var em:ErrorMessage = new ErrorMessage();

        public function GameService() {
            remoteObject = new RemoteObject();
            remoteObject.endpoint = Config.gameServerUrl;
            remoteObject.requestTimeout = Config.requestTimeout;
            remoteObject.concurrency = Config.remoteObjectConcurrency;
            remoteObject.showBusyCursor = true;
            remoteObject.addEventListener(InvokeEvent.INVOKE, blockApp);
            this.addEventListeners(unblockApp, unblockApp);
        }

        private function blockApp(event:InvokeEvent):void {
            Application.application.enabled = false;
        }

        private function unblockApp(event:*):void {
            Application.application.enabled = true;
        }

        public function get userId():int {
            return this.model.userVo.id;
        }

        public function get authinfo():String {
            return this.model.userVo.authinfo;
        }

        public function get gameId():int {
            return this.model.gameVo.id;
        }

        public function get gameSettingId():int {
            return this.model.gameSettingVo.id;
        }

        // get data to initalize game
        public function getInitGameData():void {
            this.addEventListeners(onGetInitGameDataSuccess, onGetInitGameDataFault);
            this.remoteObject.getInitGameData({"user_id": userId,
                                               "user_auth_info": authinfo},
                                              gameId);
        }

        private function onGetInitGameDataSuccess(result:ResultEvent):void {
            this.removeEventListeners(onGetInitGameDataSuccess, onGetInitGameDataFault);
            this.model.userVo.update(result.message.body.userInfo);
            this.model.gameSettingVo.update(result.message.body.gameSetting);
        }

        private function onGetInitGameDataFault(fault:FaultEvent):void {
            this.removeEventListeners(onGetInitGameDataSuccess, onGetInitGameDataFault);
            em.data = checkFaultMessage(fault);
            em.retryMethod = getInitGameData;
            PopUpMessageManager.popUpUnique(em);
        }

        // get user info
        public function getUserInfo():void {
            this.addEventListeners(onGetUserInfoSuccess, onGetUserInfoFault);
            this.remoteObject.getUserInfo(userId);
        }

        private function onGetUserInfoSuccess(result:ResultEvent):void {
            this.removeEventListeners(onGetUserInfoSuccess, onGetUserInfoFault);
            this.model.userVo.update(result.message.body.userInfo);
        }

        private function onGetUserInfoFault(fault:FaultEvent):void {
            this.removeEventListeners(onGetUserInfoSuccess, onGetUserInfoFault);
            em.data = checkFaultMessage(fault);
            PopUpMessageManager.popUpUnique(em);
        }

        // get game settings
        public function getGameSetting():void {
            this.addEventListeners(onGetGameSettingSuccess, onGetGameSettingFault);
            this.remoteObject.getGameSetting(gameId);
        }

        private function onGetGameSettingSuccess(result:ResultEvent):void {
            this.removeEventListeners(onGetGameSettingSuccess, onGetGameSettingFault);
            this.model.gameSettingVo.update(result.message.body.gameSetting);
        }

        private function onGetGameSettingFault(fault:FaultEvent):void {
            this.removeEventListeners(onGetGameSettingSuccess, onGetGameSettingFault);
            em.data = checkFaultMessage(fault);
            em.retryMethod = getGameSetting;
            PopUpMessageManager.popUpUnique(em);
        }

        public function checkFaultMessage(fault:*):String {
            if (fault.message && fault.message.hasOwnProperty("faultCode") && fault.message.hasOwnProperty("faultString")) {
                var faultCode:String = fault.message.faultCode;
                if (faultCode == "Client.Error.MessageSend") {
                    return Constants.CONN_GAME_SERVER_LOST;
                } else if (faultCode == "ServerError" ||
                           faultCode == "UserError" ||
                           faultCode == "ClientError") {
                    if (fault.message.faultString) {
                        return fault.message.faultString;
                    }
                }
            }
            return Constants.DEFAULT_ERROR_MESSAGE;
        }

        public function removeEventListeners(onSuccess:Function,
                                              onFault:Function):void {
            this.remoteObject.removeEventListener(ResultEvent.RESULT,
                                                  onSuccess);
            this.remoteObject.removeEventListener(FaultEvent.FAULT,
                                                  onFault);
        }

        public function addEventListeners(onSuccess:Function,
                                          onFault:Function):void {
            this.remoteObject.addEventListener(ResultEvent.RESULT,
                                               onSuccess);
            this.remoteObject.addEventListener(FaultEvent.FAULT,
                                               onFault);
        }
    }
}
